package com.beerandjesus.photogallery.thumbnail;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.File;
import java.util.Iterator;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;

import com.beerandjesus.common.io.TokenizedFile;

public class CreateThumbnail {
    public static final String THUMBNAIL_TOKEN_DELIMETER = "_tn";

    public static void main(String[] args) {
        if (args.length < 3) {
            System.out.println("Usage: " +
                    "java Thumbnail <original filename> <thumbnail filename> <maximum dimension>");
            return;
        }
        try {
            // original file
            TokenizedFile original = new TokenizedFile(new File(args[0]));
            // thumbnail file
            File thumbnail = new File(args[1]);
            // maximum dimension
            int maxDimension = Integer.parseInt(args[2]);

            createThumbnail(original, thumbnail, maxDimension);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * Reads an image in a file and creates
     * a thumbnail in another file.
     *
     * @param original     The name of image file.
     * @param thumb        The name of thumbnail file.
     *                     Will be created if necessary.
     * @param maxDimension The width and height of
     *                     the thumbnail must
     */
    public static void createThumbnail(TokenizedFile original, File thumb, int maxDimension) throws IOException {

        ImageReader reader = getReader(original.extension());
        ImageInputStream inputStream = ImageIO.createImageInputStream(original.asFile());
        reader.setInput(inputStream, true);

        BufferedImage bufferedImage = reader.read(0);
        reader.dispose();
        BufferedImage scaledImage = scaleBufferedImage(bufferedImage, maxDimension);
        writeImage(scaledImage, thumb);
    }

    private static Dimension getScaledDimension(int width, int height, int maxDimension) {
        double scale = (double) maxDimension / (double) height;
        if (width > height) {
            scale = (double) maxDimension / (double) width;
        }
        // Determine size of new image.
        //One of them should equal maxDimension.
        int scaledW = (int) (scale * width);
        int scaledH = (int) (scale * height);
        return new Dimension(scaledW, scaledH);
    }

    private static void writeImage(BufferedImage bufferedImage, File file) throws IOException {
        TokenizedFile tokenizedFile = new TokenizedFile(file);

        String extension = tokenizedFile.extension();
        ImageWriter writer = getWriter(extension);

        ImageOutputStream ios = ImageIO.createImageOutputStream(file);
        writer.setOutput(ios);
        writer.write(bufferedImage);
        writer.dispose();
    }

    private static BufferedImage scaleBufferedImage(BufferedImage bufferedImage, int maxDimension) {
        Dimension scaledDimension = getScaledDimension(bufferedImage.getWidth(), bufferedImage.getHeight(), maxDimension);
        int width = scaledDimension.width;
        int height = scaledDimension.height;
        BufferedImage newImage = new BufferedImage(width, height, bufferedImage.getType());
        newImage.createGraphics().drawImage(bufferedImage, 0, 0, width, height, null);
        return newImage;
    }

    private static ImageWriter getWriter(String extension) {
        Iterator writers = ImageIO.getImageWritersByFormatName(extension);
        ImageWriter writer = (ImageWriter) writers.next();
        return writer;
    }

    private static ImageReader getReader(String extension) {
        Iterator readers = ImageIO.getImageReadersByFormatName(extension);
        ImageReader reader = (ImageReader) readers.next();
        return reader;
    }

}
